#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>

#define BUFSIZE 128

int get_user_input(char **input_line, size_t *line_size);
int parse_command(char *line, char **pars);
void execute_command(char **pars);

int main(void) 
{
    char *pars[BUFSIZE] = {};
    char *input_line = NULL;
    size_t line_size = 0;
    int i;

    while (1) {
        /* 1. 获取用户输入 */
        if (!get_user_input(&input_line, &line_size)) 
            continue;

        /* 2. 解析命令     */
        if (!parse_command(input_line, pars)) {
            memset(input_line, '\0', line_size);
            continue;
        }

        /* 3. 执行命令     */
        execute_command(pars);

        memset(input_line, '\0', line_size);
    }

    return 0;
}

/* 获取用户输入 */
int get_user_input(char **input_line, size_t *line_size) 
{
    ssize_t read;

    printf(">:");
    fflush(stdout);             // 刷新缓冲区
    read = getline(input_line, line_size, stdin);

    if (-1 == read) {
        free(*input_line);      // getline 失败
        *input_line = NULL;
        return 0;
    }

    return 1;
}

/* 解析命令 */
int parse_command(char *line, char **pars) 
{
    char *token = NULL;
    int i = 0;

    if (!line) 
        return 0;

    /* 分割字符串 */
    while ((token = strsep(&line, " \t\n")) != NULL) {
        if (!strcmp(token, ""))      // 跳过空token（多个连续空格的情况）
            continue;

        if (i >= BUFSIZE - 1) {
            fprintf(stderr, "命令参数过多，最大支持 %d 个参数\n", BUFSIZE - 1);
            return 0;
        }

        pars[i++] = token;
    }
    pars[i] = NULL;                  // execvp 要求的 NULL 结尾

    return 1;
}

/* 执行命令 */
void execute_command(char **pars) 
{
    pid_t pid = fork();

    if (-1 == pid) {
        perror("fork()");
        return;
    }

    if (0 == pid) {          // 子进程
        execvp(pars[0], pars);
        perror("execvp()");  // 如果execvp返回说明执行失败
    } else {                 // 父进程
        wait(NULL);
    }
}

